from fastapi import UploadFile
import aiofiles
import asyncio
import os

from settings import settings
from common.exception.errors import CustomException

class AsyncFileUtils:
    """异步文件操作类

    """
    
    @staticmethod
    async def read_file_str(file_path: str) -> str:
        """以字符方式读取文件

        Args:
            file_path (str): 文件路径

        Returns:
            str: 文件内容
        """
        async with aiofiles.open(file_path, mode='r') as file:
            content = await file.read()
        return content
    
    @staticmethod
    async def write_file_str(file_path: str, content: str) -> bool:
        """以字符方式写文件

        Args:
            file_path (str): 文件路径
            
        Returns:
            bool: True 文件写入成功
        """
        async with aiofiles.open(file_path, mode='w') as file:
            await file.write(content)
            
        return True
    
    @staticmethod
    async def create_directory(dir_path: str) -> bool:
        """路径不存在则创建，否则不做处理

        Args:
            dir_path (str): 路径

        Returns:
            bool: True 路径创建成功
        """
        if not os.path.exists(dir_path):
            loop = asyncio.get_running_loop()
            await loop.run_in_executor(None, os.makedirs, dir_path)
        return True
        
    @staticmethod
    async def read_file_binary(file_path: str) -> bytes:
        """以二进制方式读取文件

        Args:
            file_path (str): 文件路径

        Returns:
            bytes: 文件内容
        """
        async with aiofiles.open(file_path, mode='rb') as file:
            content = await file.read()
        return content
    
    @staticmethod
    async def write_file_binary(file_path: str, content: bytes) -> bool:
        """以二进制的方式写文件

        Args:
            file_path (str): 文件路径
            content (bytes): 文件内容
            
        Returns:
            bool: True 文件写入成功
        """
        async with aiofiles.open(file_path, mode='wb') as file:
            await file.write(content)
        return True
            

    @staticmethod
    async def list_directory(dir_path: str) -> list[str]:
        """列出目录下的文件

        Args:
            dir_path (str): 目录路径

        Raises:
            NotADirectoryError: 非有效路径异常

        Returns:
            list[str]: 文件列表
        """
        if os.path.exists(dir_path) and os.path.isdir(dir_path):
            loop = asyncio.get_running_loop()
            files = await loop.run_in_executor(None, os.listdir, dir_path)
            return files
        else:
            raise NotADirectoryError(f"The path {dir_path} is not a valid directory.")
    
    @staticmethod
    async def exists(path: str) -> bool:
        """文件或路径是否存在

        Args:
            path (str): 文件或路径

        Returns:
            bool: True 表示存在；False 表示不存在
        """
        return os.path.exists(path)
    
    @staticmethod
    async def delete_file(file_path: str) -> bool:
        """如果文件存在，则删除文件；否则不做处理

        Args:
            file_path (str): 文件路径

        Returns:
            bool: True 操作成功
        """
        if os.path.exists(file_path):
            loop = asyncio.get_running_loop()
            await loop.run_in_executor(None, os.remove, file_path)
        return True
      
    @staticmethod  
    async def check_file(file: UploadFile, allow: list[str] = None) -> bool:
        """检查文件

        Args:
            file (UploadFile): 文件
            allow (list[str]): 允许的文件格式，如 ["doc", "pdf"]

        Returns:
            bool: True 检测通过
        """
        if file.size > settings.MAX_FILE:
            raise CustomException(
                code=500,
                msg="文件小大超过500M"
            )
        if allow:
            file_extension = file.filename.split(".")[-1].lower()
            if file_extension not in allow:
                raise CustomException(
                    code=500,
                    msg=f"文件非 {allow}，格式错误"
                )
        return True